const nodemailer = require('nodemailer');
const SMSClient = require('@alicloud/sms-sdk');
const JPush = require('jpush-sdk');
const config = require('../config');
const { logger } = require('../utils/logger');
const queueService = require('./queue.service');

class NotificationService {
  /**
   * 发送邮件
   * @param {string} to - 收件人
   * @param {string} subject - 主题
   * @param {string} html - 内容
   * @returns {Promise<Object>} - 发送结果
   */ 
  constructor() {
    // Initialize email transporter
    this.emailTransporter = nodemailer.createTransport({
      host: config.email.host,
      port: config.email.port,
      secure: config.email.secure,
      auth: {
        user: config.email.user,
        pass: config.email.password
      }
    });

    // Initialize SMS client
    this.smsClient = new SMSClient({
      accessKeyId: config.sms.accessKeyId,
      secretAccessKey: config.sms.secretAccessKey
    });

    // Initialize JPush client
    this.jpushClient = JPush.buildClient(config.jpush.appKey, config.jpush.masterSecret);

    // Initialize notification queues
    this.initializeQueues();
  }

  /**
   * 初始化通知队列
   */
  initializeQueues() {
    // Email queue
    queueService.createQueue('email', async (job) => {
      const { to, subject, html } = job.data;
      await this.sendEmail(to, subject, html);
    });

    // SMS queue
    queueService.createQueue('sms', async (job) => {
      const { phoneNumber, templateCode, templateParam } = job.data;
      await this.sendSMS(phoneNumber, templateCode, templateParam);
    });

    // Push notification queue
    queueService.createQueue('push', async (job) => {
      const { audience, notification, message } = job.data;
      await this.sendPushNotification(audience, notification, message);
    });
  }

  /**
   * 发送邮件
   * @param {string} to - 收件人
   * @param {string} subject - 主题
   * @param {string} html - 内容
   * @returns {Promise<Object>} - 发送结果
   */
  async sendEmail(to, subject, html) {
    try {
      const info = await this.emailTransporter.sendMail({
        from: config.email.from,
        to,
        subject,
        html
      });
      logger.info('Email sent:', info.messageId);
      return info;
    } catch (error) {
      logger.error('Email send error:', error);
      throw error;
    }
  }

  /**
   * 发送短信
   * @param {string} phoneNumber - 手机号
   * @param {string} templateCode - 模板ID
   * @param {Object} templateParam - 模板参数
   * @returns {Promise<Object>} - 发送结果
   */
  async sendSMS(phoneNumber, templateCode, templateParam) {
    try {
      const result = await this.smsClient.sendSMS({
        PhoneNumbers: phoneNumber,
        SignName: config.sms.signName,
        TemplateCode: templateCode,
        TemplateParam: JSON.stringify(templateParam)
      });
      logger.info('SMS sent:', result);
      return result;
    } catch (error) {
      logger.error('SMS send error:', error);
      throw error;
    }
  }

  /**
   * 发送推送通知
   * @param {string} audience - 接收者
   * @param {Object} notification - 通知内容
   * @param {Object} message - 消息内容
   * @returns {Promise<Object>} - 发送结果
   */
  async sendPushNotification(audience, notification, message) {
    try {
      const result = await this.jpushClient.push()
        .setPlatform('all')
        .setAudience(audience)
        .setNotification(notification)
        .setMessage(message)
        .send();
      logger.info('Push notification sent:', result);
      return result;
    } catch (error) {
      logger.error('Push notification error:', error);
      throw error;
    }
  }

  /**
   * 添加邮件队列任务
   * @param {string} to - 收件人
   * @param {string} subject - 主题
   * @param {string} html - 内容
   * @param {Object} options - 选项
   * @returns {Promise<Object>} - 任务ID
   */
  async queueEmail(to, subject, html, options = {}) {
    return await queueService.addJob('email', { to, subject, html }, options);
  }

  /**
   * 添加短信队列任务
   * @param {string} phoneNumber - 手机号
   * @param {string} templateCode - 模板ID
   * @param {Object} templateParam - 模板参数
   * @param {Object} options - 选项
   * @returns {Promise<Object>} - 任务ID
   */
  async queueSMS(phoneNumber, templateCode, templateParam, options = {}) {
    return await queueService.addJob('sms', { phoneNumber, templateCode, templateParam }, options);
  }

  /**
   * 添加推送通知队列任务
   * @param {string} audience - 接收者
   * @param {Object} notification - 通知内容
   * @param {Object} message - 消息内容
   * @param {Object} options - 选项
   * @returns {Promise<Object>} - 任务ID
   */
  async queuePushNotification(audience, notification, message, options = {}) {
    return await queueService.addJob('push', { audience, notification, message }, options);
  }

  /**
   * 批量发送邮件
   * @param {Array<string>} recipients - 收件人列表
   * @param {string} subject - 主题
   * @param {string} html - 内容
   * @returns {Promise<Array<Object>>} - 发送结果列表
   */
  async sendBatchEmails(recipients, subject, html) {
    const jobs = recipients.map(to => 
      this.queueEmail(to, subject, html)
    );
    return await Promise.all(jobs);
  }

  /**
   * 批量发送短信
   * @param {Array<string>} recipients - 手机号列表
   * @param {string} templateCode - 模板ID
   * @param {Object} templateParam - 模板参数
   * @returns {Promise<Array<Object>>} - 发送结果列表
   */
  async sendBatchSMS(recipients, templateCode, templateParam) {
    const jobs = recipients.map(phoneNumber => 
      this.queueSMS(phoneNumber, templateCode, templateParam)
    );
    return await Promise.all(jobs);
  }

  /**
   * 批量发送推送通知
   * @param {Array<string>} audiences - 接收者列表
   * @param {Object} notification - 通知内容
   * @param {Object} message - 消息内容
   * @returns {Promise<Array<Object>>} - 发送结果列表
   */
  async sendBatchPushNotifications(audiences, notification, message) {
    const jobs = audiences.map(audience => 
      this.queuePushNotification(audience, notification, message)
    );
    return await Promise.all(jobs);
  }

  /**
   * 获取通知状态
   * @param {string} type - 类型
   * @param {string} jobId - 任务ID
   * @returns {Promise<Object>} - 任务状态
   */
  async getNotificationStatus(type, jobId) {
    return await queueService.getJob(type, jobId);
  }

  /**
   * 取消通知任务
   * @param {string} type - 类型
   * @param {string} jobId - 任务ID
   * @returns {Promise<boolean>} - 取消结果
   */
    async cancelNotification(type, jobId) {
    return await queueService.removeJob(type, jobId);
  }

  /**
   * 获取队列状态
   * @param {string} type - 类型
   * @returns {Promise<Object>} - 队列状态
   */
  async getQueueStatus(type) {
    return await queueService.getQueueStatus(type);
  }
}

module.exports = new NotificationService(); 